﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;

namespace Workflows.Components.ETL
{
    /// <summary></summary>
    [Serializable]
    public class GrabDataInstruction:InstructionBase
    {
        #region members
        private DataProviderType _KeyDataProvider;
        /// <summary></summary>
        public DataProviderType KeyDataProvider
        {
            get
            {
                return this._KeyDataProvider;
            }
            set
            {
                this._KeyDataProvider = value;
            }
        }

        private string _KeyConnStr;
        /// <summary></summary>
        public string KeyConnStr
        {
            get
            {
                return this._KeyConnStr;
            }
            set
            {
                this._KeyConnStr = value;
            }
        }

        private string _KeySql;
        /// <summary></summary>
        public string KeySql
        {
            get
            {
                return this._KeySql;
            }
            set
            {
                this._KeySql = value;
            }
        }

        private DataProviderType _SrcDataProvider;
        /// <summary></summary>
        public DataProviderType SrcDataProvider
        {
            get
            {
                return this._SrcDataProvider;
            }
            set
            {
                this._SrcDataProvider = value;
            }
        }

        private string _SrcConnStr;
        /// <summary></summary>
        public string SrcConnStr
        {
            get
            {
                return this._SrcConnStr;
            }
            set
            {
                this._SrcConnStr = value;
            }
        }

        private string _SrcDataSql;
        /// <summary></summary>
        public string SrcDataSql
        {
            get
            {
                return this._SrcDataSql;
            }
            set
            {
                this._SrcDataSql = value;
            }
        }

        private DataProviderType _TgtDataProvider;
        /// <summary></summary>
        public DataProviderType TgtDataProvider
        {
            get
            {
                return this._TgtDataProvider;
            }
            set
            {
                this._TgtDataProvider = value;
            }
        }

        private string _TgtConnStr;
        /// <summary></summary>
        public string TgtConnStr
        {
            get
            {
                return this._TgtConnStr;
            }
            set
            {
                this._TgtConnStr = value;
            }
        }

        private string _TgtTableName;
        /// <summary></summary>
        public string TgtTableName
        {
            get
            {
                return this._TgtTableName;
            }
            set
            {
                this._TgtTableName = value;
            }
        }

        private List<GrabDataFieldMapping> _FieldMappings;
        /// <summary></summary>
        public List<GrabDataFieldMapping> FieldMappings
        {
            get
            {
                return this._FieldMappings;
            }
            set
            {
                this._FieldMappings = value;
            }
        }

        private string _NonNullFieldSkipUpdate;
        /// <summary></summary>
        public string NonNullFieldSkipUpdate
        {
            get
            {
                return this._NonNullFieldSkipUpdate;
            }
            set
            {
                this._NonNullFieldSkipUpdate = value;
            }
        }

        private string _LogFilePath;
        /// <summary></summary>
        public string LogFilePath
        {
            get
            {
                return this._LogFilePath;
            }
            set
            {
                this._LogFilePath = value;
            }
        }

        private string _ErrorFilePath;
        /// <summary></summary>
        public string ErrorFilePath
        {
            get
            {
                return this._ErrorFilePath;
            }
            set
            {
                this._ErrorFilePath = value;
            }
        }

        private bool _UseBcp;
        /// <summary></summary>
        public bool UseBcp
        {
            get
            {
                return this._UseBcp;
            }
            set
            {
                this._UseBcp = value;
            }
        }
        #endregion

        /// <summary></summary>
        public GrabDataInstruction():base(Guid.Empty,Guid.Empty)
        {
            this._KeyDataProvider = DataProviderType.MSSQL;
            this._KeyConnStr = "";
            this._KeySql = string.Empty;

            this._SrcDataProvider = DataProviderType.Oracle;
            this._SrcConnStr = string.Empty;
            this._SrcDataSql = string.Empty;

            this._TgtDataProvider = DataProviderType.MSSQL;
            this._TgtConnStr = "";
            this._TgtTableName = string.Empty;
            this._NonNullFieldSkipUpdate = string.Empty;
            this._FieldMappings=new List<GrabDataFieldMapping>();
            this._UseBcp = false;

            this._LogFilePath = string.Empty;
            this._ErrorFilePath = string.Empty;
            
        }

        /// <summary></summary>
        public GrabDataInstruction(Guid componentID, Guid jobTicketID,
            DataProviderType keyDbProvider,
            string keyConnStr,
            string keySql,
            DataProviderType srcDbProvider,
            string srcConnStr,
            string srcSql,
            DataProviderType tgtDbProvider,
            string tgtConnStr,
            string tgtTableName,
            string nonNullFieldSkip,
            List<GrabDataFieldMapping> fieldMappings,
            bool useBcp,
            string logFilePath,
            string errFilePath) 
            : base(componentID, jobTicketID)
        {
            this._KeyDataProvider = keyDbProvider;
            this._KeyConnStr = keyConnStr;
            this._KeySql = keySql;

            this._SrcDataProvider = srcDbProvider;
            this._SrcConnStr = srcConnStr;
            this._SrcDataSql = srcSql;

            this._TgtDataProvider = tgtDbProvider;
            this._TgtConnStr = tgtConnStr;
            this._TgtTableName = tgtTableName;
            this._NonNullFieldSkipUpdate = nonNullFieldSkip;
            this._FieldMappings = fieldMappings;
            this._UseBcp = useBcp;

            this._LogFilePath = logFilePath;
            this._ErrorFilePath = errFilePath;
        }

        public override XmlNode Serialize(ref XmlDocument xDoc, ref XmlNode parentNode)
        {
            XmlNode xNode = XmlDataUtil.AddElement(ref xDoc, parentNode, "Instruction");
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "Type", this.GetType().FullName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ComponentID", this.OwnerComponentID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "WorkerID", this.OwnerWorkerInstanceID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SubmitTime", this.SubmitTime.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "StartTime", this.StartTime.ToString());

            XmlDataUtil.UpdateAttribute(ref xDoc,xNode, "KeyDataProvider",((int)this.KeyDataProvider).ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "KeyConnectionStr", this.KeyConnStr);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "KeySql", this.KeySql);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SrcDataProvider", ((int) this.SrcDataProvider).ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SrcConnectionStr", this.SrcConnStr);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SrcDataSql", this.SrcDataSql);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TgtDataProvider", ((int) this.TgtDataProvider).ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TgtConnectionStr", this.TgtConnStr);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TgtTableName", this.TgtTableName);
            XmlDataUtil.UpdateAttribute(ref xDoc,xNode, "NonNullFieldSkipUpdate", this.NonNullFieldSkipUpdate);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode,"UseBcp",this.UseBcp.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "LogFilePath", this.LogFilePath);
            XmlDataUtil.UpdateAttribute(ref xDoc,xNode,"ErrorFilePath",this.ErrorFilePath);

            if(this.FieldMappings !=null && this.FieldMappings.Count>0)
            {
                XmlNode fieldMappingRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "FieldMappings");
                foreach(GrabDataFieldMapping fieldMapping in this.FieldMappings)
                {
                    XmlNode fieldMappingNode = XmlDataUtil.AddElement(ref xDoc, fieldMappingRootNode, "FieldMapping");
                    XmlDataUtil.UpdateAttribute(ref xDoc,fieldMappingNode,"SrcField",fieldMapping.SrcField);
                    XmlDataUtil.UpdateAttribute(ref xDoc,fieldMappingNode,"TgtField",fieldMapping.TgtField);
                    XmlDataUtil.UpdateAttribute(ref xDoc,fieldMappingNode,"Action",((int)fieldMapping.Action).ToString());
                }
            }

            return xNode;
        }

        public override InstructionBase Instantiate(XmlNode xNode)
        {
            if (xNode.Attributes.GetNamedItem("Type").Value == this.GetType().FullName)
            {
                GrabDataInstruction instruction = new GrabDataInstruction();
                instruction.OwnerComponentID = new Guid(XmlDataUtil.GetAttributeValue(xNode, "ComponentID", Guid.NewGuid().ToString()));
                instruction.OwnerWorkerInstanceID = new Guid(XmlDataUtil.GetAttributeValue(xNode, "WorkerID", Guid.NewGuid().ToString()));
                instruction.SubmitTime = DateTime.Parse(XmlDataUtil.GetAttributeValue(xNode, "SubmitTime", TimeUtil.DbMinTime.ToString()));
                instruction.StartTime = DateTime.Parse(XmlDataUtil.GetAttributeValue(xNode, "StartTime", TimeUtil.DbMinTime.ToString()));

                instruction.KeyDataProvider =
                    (DataProviderType) int.Parse(XmlDataUtil.GetAttributeValue(xNode, "KeyDataProvider", ((int)DataProviderType.MSSQL).ToString()));
                instruction.KeyConnStr = XmlDataUtil.GetAttributeValue(xNode, "KeyConnectionStr", string.Empty);
                instruction.KeySql = XmlDataUtil.GetAttributeValue(xNode, "KeySql", string.Empty);
                instruction.SrcDataProvider =
                    (DataProviderType) int.Parse(XmlDataUtil.GetAttributeValue(xNode, "SrcDataProvider", ((int)DataProviderType.Oracle).ToString()));
                instruction.SrcConnStr = XmlDataUtil.GetAttributeValue(xNode, "SrcConnectionStr", string.Empty);
                instruction.SrcDataSql = XmlDataUtil.GetAttributeValue(xNode, "SrcDataSql", string.Empty);
                instruction.TgtDataProvider =
                    (DataProviderType) int.Parse(XmlDataUtil.GetAttributeValue(xNode, "TgtDataProvider", ((int)DataProviderType.MSSQL).ToString()));
                instruction.TgtConnStr = XmlDataUtil.GetAttributeValue(xNode, "TgtConnectionStr", string.Empty);
                instruction.TgtTableName = XmlDataUtil.GetAttributeValue(xNode, "TgtTableName", string.Empty);
                instruction.NonNullFieldSkipUpdate = XmlDataUtil.GetAttributeValue(xNode, "NonNullFieldSkipUpdate", string.Empty);
                instruction.UseBcp = bool.Parse(XmlDataUtil.GetAttributeValue(xNode, "UseBcp", false.ToString()));
                instruction.LogFilePath = XmlDataUtil.GetAttributeValue(xNode, "LogFilePath", string.Empty);
                instruction.ErrorFilePath = XmlDataUtil.GetAttributeValue(xNode, "ErrorFilePath", string.Empty);

                instruction.FieldMappings = null;
                XmlNodeList fieldMappingNodes = xNode.SelectNodes("FieldMappings/FieldMapping");
                if(fieldMappingNodes !=null && fieldMappingNodes.Count>0)
                {
                    instruction.FieldMappings=new List<GrabDataFieldMapping>();
                    foreach(XmlNode fieldMappingNode in fieldMappingNodes)
                    {
                        GrabDataFieldMapping fieldMapping=new GrabDataFieldMapping();
                        fieldMapping.SrcField = fieldMappingNode.Attributes.GetNamedItem("SrcField").Value;
                        fieldMapping.TgtField = fieldMappingNode.Attributes.GetNamedItem("TgtField").Value;
                        fieldMapping.Action =
                            (FieldDataPopulationAction)
                            int.Parse(fieldMappingNode.Attributes.GetNamedItem("Action").Value);
                        instruction.FieldMappings.Add(fieldMapping);
                    }
                }

                return instruction;
            }
            else
            {
                throw new Exception("Unable to instantiate component: invalid type specified in xml node");
            }
        }
    }
}
